﻿using System.Collections.Generic;
using ShouldIt.Core;
using WatiN.Core;

namespace ShouldIt.Watin
{
    public static class ShouldExtensions
    {
        public static Element ShouldExist(this Element e, string failedMessage, params object[] args)
        {
            if (e == null || !e.Exists)
            {
                var message = failedMessage == null 
                    ? string.Format("Element '{0}' does not exist.", e)
                    : args == null 
                        ? failedMessage 
                        : string.Format(failedMessage, args);
                AssertProvidersContainer.Current.Fail(message);
            }
            return e;
        }

        public static Element ShouldExist(this Element e)
        {
            return e.ShouldExist(null);
        }

        public static Element ShouldExist(this Browser b, string elementId)
        {
            return b.ShouldExist(elementId, null);
        }

        public static Element ShouldExist(this Browser b, string elementId, string failedMessage, params object[] args)
        {
            return b.Element(elementId).ShouldExist();
        }

        public static Element ShouldNotExist(this Element e)
        {
            return e.ShouldNotExist(null);
        }

        public static Element ShouldNotExist(this Element e, string failedMessage, params object[] args)
        {
            if (e != null && e.Exists)
            {
                var message = failedMessage == null
                    ? string.Format("Element '{0}' exists.", e)
                    : args == null
                        ? failedMessage
                        : string.Format(failedMessage, args);
                AssertProvidersContainer.Current.Fail(message);
            }
            return e;
        }

        public static Element ShouldNotExist(this Browser b, string elementId)
        {
            return b.Element(elementId).ShouldNotExist();
        }

        public static SelectList ShouldContainOption(this SelectList s, string text)
        {
            s.ShouldContainOptions(text);
            return s;
        }

        public static SelectList ShouldContainOptions(this SelectList s, params string[] textValues)
        {
            var missing = new List<string>();
            foreach (var text in textValues)
            {
                if (!s.Option(text).Exists)
                {
                    missing.Add(text);
                }
            }
            if (missing.Count > 0)
            {
                AssertProvidersContainer.Current.Fail("Some values were not found in the select options: {0}", string.Join(", ", missing.ToArray()));
            }
            return s;
        }

        public static SelectList ShouldNotContainOptions(this SelectList s, params string[] textValues)
        {
            var unexpectedlyContains = new List<string>();
            foreach (var text in textValues)
            {
                if (s.Option(text).Exists)
                {
                    unexpectedlyContains.Add(text);
                }
            }
            if (unexpectedlyContains.Count > 0)
            {
                AssertProvidersContainer.Current.Fail("Some values that were not expected were found in the select options: {0}", string.Join(", ", unexpectedlyContains.ToArray()));
            }
            return s;
        }

        public static TextField ShouldContain(this TextField t, params string[] textValues)
        {
            var notContains = new List<string>();
            foreach (var text in textValues)
            {
                if (!t.Value.Contains(text))
                {
                    notContains.Add(text);
                }
            }
            if (notContains.Count > 0)
            {
                AssertProvidersContainer.Current.Fail("Some values were not found in the text field value: {0}", string.Join(", ", notContains.ToArray()));
            }
            return t;
        }
    }
}